package com.iotechn.unimall.admin.api.cacheManage;

import com.iotechn.unimall.core.exception.ServiceException;
import com.iotechn.unimall.data.component.CacheComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 缓存实现类
 *
 * @author kyms
 * @date 2020-05-13 13:57
 */
@Service
public class CacheManageServiceImpl implements CacheManageService {
    private static final String CA_CATEGORY_TREE = "CA_CATEGORY_TREE";

    private static final String CA_CATEGORY_CHILDREN_KEY = "CA_CATEGORY_CHILDREN_";

    private static final String ADMIN_QUERY_CATEGORY_LIST = "ADMIN_QUERY_CATEGORY_LIST";

    private static final String CA_CATEGORY_SECOND_LEVEL_TREE = "CA_CATEGORY_SECOND_LEVEL_TREE";
    private static final String CA_CATEGORY_LIST = "CA_CATEGORY_LIST";
    private static final String CA_CATEGORY_ID_HASH = "CA_CATEGORY_ID_HASH";
    private static final String CA_USER_COLLECT_HASH = "CA_USER_COLLECT_";
    /**
     * SPU 分页缓存
     */
    private static final String CA_SPU_PAGE_PREFIX = "CA_SPU_PAGE_";
    /**
     * SPU DTO 缓存  CA_SPU_+spuId
     */
    private static final String CA_SPU_PREFIX = "CA_SPU_";
    /**
     * SPU 销量缓存
     */
    private static final String CA_SPU_SALES_HASH = "CA_SPU_SALES_HASH";
    /**
     * SPU DO 缓存，加速 getById...  hashKey = 'S' + spuId
     */
    private static final String CA_SPU_HASH = "CA_SPU_HASH";
    private static final String CA_APPRAISE_KEY = "CA_APPRAISE_";
    private static final String CA_DISTRIBUTION_STRATEGY_SPU = "CA_DISTRIBUTION_STRATEGY_SPU_";
    private static final String RECOMMEND_NAME = "RECOMMEND_TYPE_";
    private static final String CA_CONFIG_DTO_KEY = "CA_CONFIG_DTO_KEY";
    private static final String CA_OFFICIAL_WECHAT_ACCESS = "CA_OFFICIAL_WECHAT_ACCESS";

    private static final String CA_OFFICIAL_WECHAT_TICKET = "CA_OFFICIAL_WECHAT_TICKET";

    private static final String CA_MINI_WECHAT_ACCESS = "CA_MINI_WECHAT_ACCESS";

    private static final String ADDRESSDIVISIONDOS = "large:addressdivisiondos";
    private static final String ADDRESSCOUNTCACHR = "large:count";

    private static final String ADDRESSMAPCACHE= "large:map:";
    private static final String ADDRESSKEY="large:address:";

    //缓存
    private final static List<String> CACHE_KEY_LIST = new LinkedList<>();
    private static final Logger logger = LoggerFactory.getLogger(CacheManageServiceImpl.class);

    static {
        CACHE_KEY_LIST.add(CA_CATEGORY_TREE);
        CACHE_KEY_LIST.add(CA_OFFICIAL_WECHAT_ACCESS);
        CACHE_KEY_LIST.add(CA_OFFICIAL_WECHAT_TICKET);
        CACHE_KEY_LIST.add(CA_OFFICIAL_WECHAT_TICKET);
        CACHE_KEY_LIST.add(CA_MINI_WECHAT_ACCESS);
        CACHE_KEY_LIST.add(ADMIN_QUERY_CATEGORY_LIST);
        CACHE_KEY_LIST.add(CA_CATEGORY_SECOND_LEVEL_TREE);
        CACHE_KEY_LIST.add(CA_CATEGORY_LIST);
        CACHE_KEY_LIST.add(CA_CATEGORY_ID_HASH);
        CACHE_KEY_LIST.add(CA_USER_COLLECT_HASH);
        CACHE_KEY_LIST.add(CA_SPU_PAGE_PREFIX);
        CACHE_KEY_LIST.add(CA_SPU_PREFIX);
        CACHE_KEY_LIST.add(CA_SPU_SALES_HASH);
        CACHE_KEY_LIST.add(CA_SPU_HASH);
        CACHE_KEY_LIST.add(CA_APPRAISE_KEY);
        CACHE_KEY_LIST.add(CA_DISTRIBUTION_STRATEGY_SPU);
        CACHE_KEY_LIST.add(RECOMMEND_NAME);
        CACHE_KEY_LIST.add(CA_CONFIG_DTO_KEY);
        CACHE_KEY_LIST.add(CA_CATEGORY_CHILDREN_KEY);
        CACHE_KEY_LIST.add(ADDRESSDIVISIONDOS);
        CACHE_KEY_LIST.add(ADDRESSCOUNTCACHR);
        CACHE_KEY_LIST.add(ADDRESSMAPCACHE);
        CACHE_KEY_LIST.add(ADDRESSKEY);


    }

    @Autowired
    private CacheComponent cacheComponent;

    @Override
    public List<Map<String, Object>> listAllCacheKey(Long adminId) throws ServiceException {
        List<Map<String, Object>> allCacheKeys = new LinkedList<>();
        Map<String, List<String>> prefixKeyMap = new ConcurrentHashMap<>();
        for (String key : CACHE_KEY_LIST) {
            Set<String> prefixKeyList = cacheComponent.getPrefixKeySet(key);
            if (prefixKeyList == null || prefixKeyList.size() == 0) {
                continue;
            }
            for (String s : prefixKeyList) {
                if (prefixKeyMap.containsKey(key)) {
                    prefixKeyMap.get(key).add(s);
                } else {
                    List<String> prefixKeys = new LinkedList<>();
                    prefixKeys.add(s);
                    prefixKeyMap.put(key, prefixKeys);
                }
            }
        }
        prefixKeyMap.forEach((k, v) -> {
            Map<String, Object> map = new ConcurrentHashMap<>();
            map.put("prefix", k);
            map.put("keys", v);
            allCacheKeys.add(map);
        });
        return allCacheKeys;
    }


    @Autowired
    private StringRedisTemplate userRedisTemplate;
    @Override
    public Object clearAllCacheKey(Long adminId) throws ServiceException {
        int result = 0;
        int left = 0;

        userRedisTemplate.delete(ADDRESSDIVISIONDOS);
        userRedisTemplate.delete(ADDRESSCOUNTCACHR);
        userRedisTemplate.delete(ADDRESSMAPCACHE);

        for (String key : CACHE_KEY_LIST) {
            Set<String> prefixKeyList = cacheComponent.getPrefixKeySet(key);
            if (prefixKeyList == null || prefixKeyList.size() == 0) {
                continue;
            }
            cacheComponent.delPrefixKey(key);
            logger.info("[清空缓存]:{}", key);
            result++;
        }
        //确认已经删除
        for (String key : CACHE_KEY_LIST) {
            Set<String> prefixKeyList = cacheComponent.getPrefixKeySet(key);
            if (prefixKeyList != null && prefixKeyList.size() > 0) {
                left++;
            }
        }
        logger.info("[设置的缓存总计]:{},清理后剩余:{}", result, left);
        Map<String, Integer> resultMap = new ConcurrentHashMap<>();
        resultMap.put("total", result);
        resultMap.put("left", left);
        return resultMap;
    }
}
